﻿using System;
using System.Collections.Generic;
using System.Text;
using Galaxy.ModuleInterface.Messages.Destination;
using Galaxy.ModuleInterface.Messages.Source;
using System.Runtime.Serialization;

namespace Galaxy.ModuleInterface.Messages
{
    /// <summary>Сообщение модуля Галактики</summary>
    [Serializable]
    public abstract class CGalaxyModuleMessage : IGalaxyModuleMessage, ICloneable
    {
        /// <summary>Модуль-источник сообщения</summary>
        private ISource f_Source = null;

        /// <summary>Место назначения сообщения</summary>
        private IDestination f_Destination;

        /* --------------------------------------------------------------------- */

        /// <summary>Место назначения сообщения (только для чтения)</summary>
        public virtual IDestination Destination
        {
            get { return f_Destination; }
            set
            {
                if( value == null )
                    throw new ArgumentNullException("Для сообщения не указан объект места назначения");
                f_Destination = value;
            }
        }

        /// <summary>Источник сообщения</summary>
        public virtual ISource Source
        {
            get { return f_Source; }
            set
            {
                if( value == null )
                    throw new ArgumentNullException("Для сообщения не указан объект источника сообщеня");
                f_Source = value;
            }
        }

        /* --------------------------------------------------------------------- */

        /// <summary>Сообщение модуля Галактики</summary>
        /// <param name="Source">Источник сообщения</param>
        public CGalaxyModuleMessage(IGalaxyModule Source)
        {
            f_Source = new CModuleSource(Source);
            f_Destination = new CDestination();
        }

        /// <summary>Сообщение модуля Галактики</summary>
        /// <param name="Source">Источник сообщения</param>
        public CGalaxyModuleMessage(string Source)
        {
            f_Source = new CNamedSource(Source);
            f_Destination = new CDestination();
        }

        /// <summary>Сообщение модуля Галактики</summary>
        /// <param name="Source">Источник сообщения</param>
        public CGalaxyModuleMessage(ISource Source)
        {
            f_Source = Source;
            f_Destination = new CDestination();
        }

        /// <summary>Сообщение модуля Галактики</summary>
        /// <param name="Source">Источник сообщения</param>
        /// <param name="Distination">Место назначения</param>
        public CGalaxyModuleMessage(IGalaxyModule Source, params IGalaxyModule[] Distination)
        {
            f_Source = new CModuleSource(Source);
            f_Destination = new CDestination(Distination);
        }

        /// <summary>Сообщение модуля Галактики</summary>
        /// <param name="Source">Источник сообщения</param>
        /// <param name="Distination">Место назначения</param>
        public CGalaxyModuleMessage(string Source, params IGalaxyModule[] Distination)
        {
            f_Source = new CNamedSource(Source);
            f_Destination = new CDestination(Distination);
        }

        /// <summary>Сообщение модуля Галактики</summary>
        /// <param name="Source">Источник сообщения</param>
        /// <param name="Distination">Место назначения</param>
        public CGalaxyModuleMessage(IGalaxyModule Source, params string[] Distination)
        {
            f_Source = new CModuleSource(Source);
            f_Destination = new CDestination(Distination);
        }

        /// <summary>Сообщение модуля Галактики</summary>
        /// <param name="Source">Источник сообщения</param>
        /// <param name="Distination">Место назначения</param>
        public CGalaxyModuleMessage(string Source, params string[] Distination)
        {
            f_Source = new CNamedSource(Source);
            f_Destination = new CDestination(Distination);
        }

        /// <summary>Сообщение модуля Галактики</summary>
        /// <param name="Source">Источник сообщения</param>
        /// <param name="Distination">Место назначения</param>
        public CGalaxyModuleMessage(ISource Source, IDestination Distination)
        {
            f_Source = Source;
            f_Destination = Distination;
        }

        protected CGalaxyModuleMessage(SerializationInfo info, StreamingContext context)
        {
            f_Source = info.GetValue("Source", typeof(ISource)) as ISource;
            f_Destination = info.GetValue("Destination", typeof(IDestination)) as IDestination;
        }

        /* --------------------------------------------------------------------- */

        public override string ToString()
        {
            return "Сообщение от \"" + Source.ToString() + "\" для \"" +
                Destination.ToString() + "\"";
        }

        public override int GetHashCode()
        {
            return Destination.GetHashCode() ^ Source.GetHashCode();
        }

        public override bool Equals(object obj)
        {
            if( obj is IGalaxyModuleMessage )
                return obj.GetHashCode() == this.GetHashCode();

            return base.Equals(obj);
        }

        public object Clone()
        {
            CGalaxyModuleMessage Message =
                (CGalaxyModuleMessage)this.MemberwiseClone();
            Message.f_Destination = (IDestination)this.f_Destination.Clone();
            Message.f_Source = (ISource)this.Source.Clone();

            return Message;
        }

        #region ISerializable Members

        public virtual void GetObjectData(SerializationInfo info, StreamingContext context)
        {
            info.AddValue("Source", f_Source);
            info.AddValue("Destination", f_Destination);
        }

        #endregion
    }
}
